package com.wkbb.sports.service.impl;

import java.util.*;

import com.wkbb.common.constants.RedisKeyConstant;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.common.utils.DoubleUtil;
import com.wkbb.sports.dto.*;
import com.wkbb.sports.mapper.*;
import com.wkbb.sports.model.HlifeDevice;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wkbb.common.dto.basic.StudentInfoDto;
import com.wkbb.sports.feign.BasicFeignService;
import com.wkbb.sports.model.HlifeDetect;
import com.wkbb.sports.model.HlifeDetectStudent;
import com.wkbb.sports.model.HlifeStudentDevice;
import com.wkbb.sports.service.DetectService;
import com.wkbb.sports.utils.SportsUtils;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class DetectServiceImpl implements DetectService {

    @Autowired
    HlifeDeviceMapper hlifeDeviceMapper;
    @Autowired
    HlifeStudentDeviceMapper hlifeStudentDeviceMapper;
    @Autowired
    BasicFeignService basicFeignService;
    @Autowired
    HlifeDetectMapper hlifeDetectMapper;
    @Autowired
    HlifeDetectStudentMapper hlifeDetectStudentMapper;
    @Autowired
    HlifeDetectStudentDetailMapper hlifeDetectStudentDetailMapper;
    @Autowired
    private RedisTemplateUtil redisTemplateUtil;
    @Autowired
    BasicMapper basicMapper;


    @Transactional(rollbackFor = Exception.class)
    @Override
    public HlifeDetect addDetect(HlifeDetect hlifeDetect, Byte projectKind, List<HlifeDevice> devices, Map<String, Object> params) throws Exception {
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("classId",hlifeDetect.getClassId());
        List<StudentInfoDto> slist = basicMapper.getStudentInfoList(hashMap);
        hlifeDetect.setDetectCount(slist.size());
        hlifeDetectMapper.insert(hlifeDetect);

        List<HlifeDetectStudent> listls = new ArrayList<>();
        List<HlifeStudentDevice> studDeviceList = new ArrayList<>();

        for (StudentInfoDto student : slist) {
            Optional<HlifeDevice> optionalDeviceDto = devices.stream().filter(it -> it.getGroupIndex() == student.stuIndex() ).findFirst();
            if (optionalDeviceDto.isPresent()){
                HlifeDevice device = optionalDeviceDto.get();
                //学生对应设备
                HlifeStudentDevice studDevice = new HlifeStudentDevice();
                studDevice.setClassId(hlifeDetect.getClassId());
                studDevice.setOrgId(hlifeDetect.getOrgId());
                studDevice.setDetectId(hlifeDetect.getId());
                studDevice.setStudentId(student.getUserId());
                studDevice.setAssignDeviceId(device.getId());
                studDevice.setDeviceMac(device.getMacAddress());
                studDevice.setDeviceName(device.getName());
                studDeviceList.add(studDevice);

                //监测学生信息
                HlifeDetectStudent hlifeDetectStudent = new HlifeDetectStudent();
                hlifeDetectStudent.setDetectId(hlifeDetect.getId());
                hlifeDetectStudent.setOrgId(hlifeDetect.getOrgId());
                hlifeDetectStudent.setGradeId(hlifeDetect.getGradeId());
                hlifeDetectStudent.setGradeName(hlifeDetect.getGradeName());
                hlifeDetectStudent.setClassId(hlifeDetect.getClassId());
                hlifeDetectStudent.setClassName(hlifeDetect.getClassName());
                hlifeDetectStudent.setTeacherId(hlifeDetect.getTeacherId());
                hlifeDetectStudent.setDeviceId(device.getName());
                hlifeDetectStudent.setStudentId(student.getUserId());
                hlifeDetectStudent.setStudentName(student.getName());
                hlifeDetectStudent.setSex(SportsUtils.getSexValue(student.getSex()).byteValue());
                hlifeDetectStudent.setStudentNo(student.getStudentNo());
                listls.add(hlifeDetectStudent);
            }
        }
        hlifeStudentDeviceMapper.insertBatch(studDeviceList);
        hlifeDetectStudentMapper.insertBatch(listls);

        return hlifeDetect;
    }


    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cancelDetect(Long id) throws Exception {
        //删除分配设备
        HlifeDetect hlifeDetect = hlifeDetectMapper.getByPrimaryKey(id);
        if (hlifeDetect != null) {
            hlifeDetectMapper.deleteStudentDevice(hlifeDetect.getClassId());
            Map<String, Object> map = new HashMap<>();
            map.put("detectId", id);
            int minHeartRate = 133 - hlifeDetect.getGradeAge();
            int maxHeartRate = 168 - hlifeDetect.getGradeAge();
            int abnormalHeartRate = 200 - hlifeDetect.getGradeAge();
            map.put("minHeartRate", minHeartRate);
            map.put("maxHeartRate", maxHeartRate);
            List<HlifeDetectStudent> list = hlifeDetectStudentMapper.getListStaticData(map);
//        List<HlifeDetectStudent> list = hlifeDetectStudentMapper.getListByMapParams(map);
            if (!list.isEmpty()) {
                int maleCount = 0;
                int femaleCount = 0;
                int totalAvg = 0;
                int totalMax = 0;
                int totalMin = 0;
                int standardNum = 0;
                int overloadNum = 0;
                int heartRateAbnormalCount = 0;
                double totalDensity = 0;
                for (HlifeDetectStudent hlifeDetectStudent : list) {
//            HlifeDetectStudent res = hlifeDetectStudentDetailMapper.selStaticData(hlifeDetectStudent.getId());
//            if (null != res) {
//                res.setId(hlifeDetectStudent.getId());
                    //综合评价 1无数据 2加油 3达标 4适量
                    if (hlifeDetectStudent.getAvgHeartRate() == null) {
                        hlifeDetectStudent.setSportStatus(1);
                    } else {
                        if (hlifeDetectStudent.getSportDensity() < 0.7) {
                            hlifeDetectStudent.setSportStatus(2);
                        } else {
                            if (hlifeDetectStudent.getAvgHeartRate() > maxHeartRate) {
                                overloadNum++;
                                hlifeDetectStudent.setSportStatus(4);
                            } else {
                                standardNum++;
                                hlifeDetectStudent.setSportStatus(3);
                            }
                        }
                        if (hlifeDetectStudent.getHighHeartRate() > abnormalHeartRate) {
                            heartRateAbnormalCount++;
                        }

                        totalAvg += hlifeDetectStudent.getAvgHeartRate();
                        totalMax += hlifeDetectStudent.getHighHeartRate();
                        totalMin += hlifeDetectStudent.getLowHeartRate();
                        totalDensity += hlifeDetectStudent.getSportDensity();
                    }
                    if (hlifeDetectStudent.getSex() == 1) {
                        maleCount += 1;
                    } else if (hlifeDetectStudent.getSex() == 2) {
                        femaleCount += 1;
                    }
//                    hlifeDetectStudentMapper.update(hlifeDetectStudent);
                }
                hlifeDetectStudentMapper.updateBatch(list);
                hlifeDetect.setAvgHeartRate(totalAvg > 0 ? totalAvg / list.size() : 0);
                hlifeDetect.setLowHeartRate(totalMin > 0 ? totalMin / list.size() : 0);
                hlifeDetect.setHighHeartRate(totalMax > 0 ? totalMax / list.size() : 0);
                if (totalDensity > 0) {
                    hlifeDetect.setSportDensity(DoubleUtil.round(totalDensity / list.size(), 2));
                    if (hlifeDetect.getSportDensity() < 0.7) {
                        hlifeDetect.setSportType(1);
                    } else if (hlifeDetect.getAvgHeartRate() > maxHeartRate) {
                        hlifeDetect.setSportType(3);
                    } else {
                        hlifeDetect.setSportType(2);
                    }
                }
                hlifeDetect.setMaleCount(maleCount);
                hlifeDetect.setFemaleCount(femaleCount);
                hlifeDetect.setStandardNum(standardNum);
                hlifeDetect.setOverloadNum(overloadNum);
                hlifeDetect.setHeartRateAbnormalCount(heartRateAbnormalCount);
                hlifeDetectMapper.update(hlifeDetect);
            }
        }
    }

    @Override
    @Transactional(readOnly=true)
    public HlifeDetect getDetectChartData(Long id) throws Exception {
        String redisKey = RedisKeyConstant.SPORTS + "getDetectChartData:"+id;
        HlifeDetect hlifeDetect = (HlifeDetect)redisTemplateUtil.get(redisKey);
        if (hlifeDetect != null) return hlifeDetect;
        hlifeDetect = hlifeDetectMapper.getByPrimaryKey(id);
        if (hlifeDetect != null) {
            Map<String, Object> map = new HashMap<>();
            map.put("detectId", id);
            List<HlifeDetectStudent> list = hlifeDetectStudentMapper.getListByMapParams(map);
            //班级各心率区间人数分布
            String[] heartRateStrs = new String[]{"120", "130", "140", "150", "160", "170",""};
            List<ChartDto> heartRateNums = new ArrayList<>();
            for (int i = 0; i < heartRateStrs.length; i++) {
                String str = heartRateStrs[i];
                ChartDto chartDto = new ChartDto();
                chartDto.setDesc(str);
                chartDto.setIndex(i + 1);
                heartRateNums.add(chartDto);
            }
            //班级各练习密度区间人数分布
            String[] sportDensityStrs = new String[]{"30%", "40%", "50%", "100%"};
            List<ChartDto> sportDensityNums = new ArrayList<>();
            for (int i = 0; i < sportDensityStrs.length; i++) {
                String str = sportDensityStrs[i];
                ChartDto chartDto = new ChartDto();
                chartDto.setDesc(str);
                chartDto.setIndex(i + 1);
                sportDensityNums.add(chartDto);
            }
            for (HlifeDetectStudent hlifeDetectStudent : list) {
                //班级各心率区间人数分布
                if (hlifeDetectStudent.getAvgHeartRate() == null || hlifeDetectStudent.getAvgHeartRate() < 120) {
                    heartRateNums.get(0).addValue();
                } else if (hlifeDetectStudent.getAvgHeartRate() < 130) {
                    heartRateNums.get(1).addValue();
                } else if (hlifeDetectStudent.getAvgHeartRate() < 140) {
                    heartRateNums.get(2).addValue();
                } else if (hlifeDetectStudent.getAvgHeartRate() < 150) {
                    heartRateNums.get(3).addValue();
                } else if (hlifeDetectStudent.getAvgHeartRate() < 160) {
                    heartRateNums.get(4).addValue();
                } else if (hlifeDetectStudent.getAvgHeartRate() < 170) {
                    heartRateNums.get(5).addValue();
                } else {
                    heartRateNums.get(6).addValue();
                }
                //班级各练习密度区间人数分布
                if (hlifeDetectStudent.getSportDensity() == null || hlifeDetectStudent.getSportDensity() < 0.3) {
                    sportDensityNums.get(0).addValue();
                } else if (hlifeDetectStudent.getSportDensity() < 0.4) {
                    sportDensityNums.get(1).addValue();
                } else if (hlifeDetectStudent.getSportDensity() < 0.5) {
                    sportDensityNums.get(2).addValue();
                } else {
                    sportDensityNums.get(3).addValue();
                }
            }
            for (ChartDto chartDto : heartRateNums) {
                chartDto.calcPercentage(list.size());
            }
            for (ChartDto chartDto : sportDensityNums) {
                chartDto.calcPercentage(list.size());
            }
            hlifeDetect.setHeartRateNums(heartRateNums);
            hlifeDetect.setSportDensityNums(sportDensityNums);

            List<DetectChartDto> chartDataDtos = hlifeDetectMapper.getDetectChartData(map);
            //班级运动强度时间分布
            String[] sportTimeStrs = new String[]{"非运动", "热身", "燃脂", "有氧", "无氧", "极限"};
            List<ChartDto> timeDistributions = new ArrayList<>();
            for (int i = 0; i < sportTimeStrs.length; i++) {
                String str = sportTimeStrs[i];
                ChartDto chartDto = new ChartDto();
                chartDto.setDesc(str);
                chartDto.setIndex(i + 1);
                timeDistributions.add(chartDto);
            }
            for (DetectChartDto chartDto : chartDataDtos) {
                //班级运动强度时间分布
                if (chartDto.getSportDensity() == null || chartDto.getSportDensity() < 0.5) {
                    timeDistributions.get(0).addValue();
                } else if (chartDto.getSportDensity() < 0.6) {
                    timeDistributions.get(1).addValue();
                } else if (chartDto.getSportDensity() < 0.7) {
                    timeDistributions.get(2).addValue();
                } else if (chartDto.getSportDensity() < 0.8) {
                    timeDistributions.get(3).addValue();
                } else if (chartDto.getSportDensity() < 0.9) {
                    timeDistributions.get(4).addValue();
                } else {
                    timeDistributions.get(5).addValue();
                }
            }
            for (ChartDto chartDto : timeDistributions) {
                chartDto.calcPercentage(chartDataDtos.size());
            }
            hlifeDetect.setTimeDistributions(timeDistributions);

            int warnHeartRate = 200 - hlifeDetect.getGradeAge();
            hlifeDetect.setWarnStuList(hlifeDetectMapper.getWarnStuList(id,warnHeartRate));
            hlifeDetect.setStudents(list);
            hlifeDetect.setChartDtos(chartDataDtos);
            redisTemplateUtil.set(redisKey,hlifeDetect);
        }
        return hlifeDetect;
    }

    @Override
    @Transactional(readOnly=true)
    public DetectStuChartDto getStuDetectChartData(Long id, Long studentId) throws Exception {
        String redisKey = RedisKeyConstant.SPORTS + "getStuDetectChartData:"+id+":"+studentId;
        DetectStuChartDto dto = (DetectStuChartDto)redisTemplateUtil.get(redisKey);
        if (dto != null) return dto;
        HlifeDetect hlifeDetect = hlifeDetectMapper.getByPrimaryKey(id);
        if (hlifeDetect != null) {
            dto = new DetectStuChartDto();

            int minHeartRate = 133 - hlifeDetect.getGradeAge();
            int maxHeartRate = 168 - hlifeDetect.getGradeAge();
            Map<String, Object> map = new HashMap<>();
            map.put("detectId", id);
            map.put("studentId", studentId);
            map.put("minHeartRate", minHeartRate);
            map.put("maxHeartRate", maxHeartRate);
            List<DetectChartDto> chartDataDtos = hlifeDetectMapper.getDetectChartData(map);
            //班级运动强度时间分布
            String[] sportTimeStrs = new String[]{"非运动", "热身", "燃脂", "有氧", "无氧", "极限"};
            List<ChartDto> timeDistributions = new ArrayList<>();
            for (int i = 0; i < sportTimeStrs.length; i++) {
                String str = sportTimeStrs[i];
                ChartDto chartDto = new ChartDto();
                chartDto.setDesc(str);
                chartDto.setIndex(i + 1);
                timeDistributions.add(chartDto);
            }
            for (DetectChartDto chartDto : chartDataDtos) {
                if (chartDto.getSportDensity() == null || chartDto.getSportDensity() < 0.5) {
                    timeDistributions.get(0).addValue();
                } else if (chartDto.getSportDensity() < 0.6) {
                    timeDistributions.get(1).addValue();
                } else if (chartDto.getSportDensity() < 0.7) {
                    timeDistributions.get(2).addValue();
                } else if (chartDto.getSportDensity() < 0.8) {
                    timeDistributions.get(3).addValue();
                } else if (chartDto.getSportDensity() < 0.9) {
                    timeDistributions.get(4).addValue();
                } else {
                    timeDistributions.get(5).addValue();
                }
            }
            for (ChartDto chartDto : timeDistributions) {
                chartDto.calcPercentage(chartDataDtos.size());
            }
            dto.setTimeDistributions(timeDistributions);

            int warnHeartRate = 200 - hlifeDetect.getGradeAge();
            map.put("warnHeartRate",warnHeartRate);
            dto.setWarnList(hlifeDetectMapper.getWarnList(map));

            map.put("courseId", hlifeDetect.getTeachCourseId());
            List<DetectProjectDto> projectList = hlifeDetectMapper.getDetectProjectList(map);
            for (DetectProjectDto projectDto:projectList){
                if (projectDto.getAvgHeartRate() == null || projectDto.getAvgHeartRate() < minHeartRate){
                    projectDto.setSportType(1);
                }else if(projectDto.getAvgHeartRate() < maxHeartRate){
                    projectDto.setSportType(2);
                }else{
                    projectDto.setSportType(3);
                }
            }
            dto.setProjectList(projectList);
            dto.setChartDtos(chartDataDtos);
            redisTemplateUtil.set(redisKey,dto);
        }
        return dto;
    }

    @Override
    @Transactional(readOnly=true)
    public HlifeDetect selDetecInfo(Long id) throws Exception {
        HlifeDetect hlifeDetect = hlifeDetectMapper.getByPrimaryKey(id);
        if (hlifeDetect != null) {
            Map<String, Object> map = new HashMap<>();
            map.put("detectId", hlifeDetect.getId());
            List<HlifeDetectStudent> hlist = hlifeDetectStudentMapper.getListByMapParams(map);
            hlifeDetect.setStudents(hlist);
			/*for(HlifeDetectStudent hlifeDetectStudent:hlist){
				List<HlifeDetectStudentDetail> hdlist =hlifeDetectStudentDetailMapper.getListByMapParams(hlifeDetectStudent.getId());
				hlifeDetectStudent.setHlifeDetectStudentDetailList(hdlist);
			}*/
        }
        return hlifeDetect;
    }


    @Override
    @Transactional(readOnly=true)
    public List<HlifeDetect> selDetectList() throws Exception {
        return hlifeDetectMapper.selDetecInfo(null);
    }


    @Override
    public HlifeDetect isExit(Long classId) throws Exception {
        return hlifeDetectMapper.isExit(classId);
    }

    @Override
    @Transactional(readOnly=true)
    public PageInfo<HlifeDetect> queryDetectList(Map<String, Object> params, int pageNo, int pageSize)
            throws Exception {
        Page<HlifeDetect> page = PageHelper.startPage(pageNo, pageSize, false);
        List<HlifeDetect> detects = hlifeDetectMapper.getListByMapParams(params);
        PageInfo<HlifeDetect> pageInfo = new PageInfo<HlifeDetect>(detects);
        pageInfo.setTotal(page.getTotal());
        return pageInfo;
    }

    @Override
    public List<String> selectUseDeviceGoup(Map<String, Object> map) throws Exception  {
        return hlifeDetectMapper.selectUseDeviceGoup(map);
    }


}
